home *** CD-ROM | disk | FTP | other *** search
- /* The main program of the X11 interface to Xconq.
- Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995
- Stanley T. Shebs.
-
- Xconq is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version. See the file COPYING. */
-
- #include "conq.h"
- extern int side_acp_human PROTO ((Side *side));
- #include "cmdline.h"
- #include "xconq.h"
-
- extern int popup_dialog; /* from cmdline.c */
-
- /* (Yes, we can compile all this with Think C on Macs - useful for prototype
- checking) */
- #ifdef THINK_C
- char *strdup(char *);
- #endif
-
- /* Local function declarations. */
-
- void notify_instructions PROTO ((void));
-
- static void quit_program PROTO ((Widget wdgt, XEvent *event, String *params, Cardinal *num_params));
-
- static void run_game_proc PROTO ((XtPointer client_data, XtIntervalId *id));
-
- static Boolean run_game_idle PROTO ((XtPointer clientdata));
-
- static int handle_x_error PROTO ((Display *dpy, XErrorEvent *evt));
- static int handle_xio_error PROTO ((Display *dpy));
- static void handle_xt_error PROTO ((String msg));
-
- void popup_game_dialog PROTO ((void));
-
- /* X-specific options, plus some NULL definitions so that they'll be
- ignored by X parsing and get passed through to the generic Xconq
- command-line parser. */
-
- XrmOptionDescRec xoptions[] = {
- { "-background", "*background", XrmoptionSepArg, NULL },
- { "-bg", "*background", XrmoptionSepArg, NULL },
- { "-display", ".display", XrmoptionSepArg, NULL },
- { "-f", NULL, XrmoptionSkipArg, NULL },
- { "-fg", "*foreground", XrmoptionSepArg, NULL },
- { "-fn", "*font", XrmoptionSepArg, NULL },
- { "-font", "*font", XrmoptionSepArg, NULL },
- { "-foreground", "*foreground", XrmoptionSepArg, NULL },
- { "-g", NULL, XrmoptionSkipArg, NULL },
- { "-geometry", "*geometry", XrmoptionSepArg, NULL },
- { "-n", NULL, XrmoptionNoArg, NULL },
- { "-name", ".name", XrmoptionSepArg, NULL },
- { "-xrm", NULL, XrmoptionResArg, NULL }
- };
-
- int xoptions_count;
-
- String fallback_resources[] = {
- /* Resources for interactive setup dialogs. */
- "*Setup*ChoicePopup*x: 100",
- "*Setup*ChoicePopup*y: 100",
-
- "*Setup*ChoiceBox*label.label: Choose a Game!",
-
- "*Setup*ScenarioPopup*x: 100",
- "*Setup*ScenarioPopup*y: 100",
-
- "*Setup*ScenarioSetup*Swap.label: Swap",
- "*Setup*ScenarioSetup*Done.label: Done",
-
- "*PortholeLabel.Translations: #override \\n ~Shift<Btn1Down>: toolaction() \\n Shift<Btn1Down>: toolselection() \\n ~Shift<Btn2Down>: select() movelook() \\n Shift<Btn2Down>: select() \\n Shift<Btn2Up>: distance() \\n <Btn3Down>: select() moveunit() \\n Meta<MotionNotify>: motionselect() movelook() \\n <Expose>: redraw() \\n <KeyPress>: keypress()",
-
- "*ListView.height: 500",
-
- "*Help.width: 400",
- "*Help.height: 800",
-
- "*helpShell*topicPort.height: 300",
- "*helpShell*topicPort.width: 100",
- "*helpShell*title.width: 500",
- "*helpShell*title.borderWidth: 0",
- "*helpShell*title.font: -*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*",
- "*helpShell*text.height: 300",
- "*helpShell*text.width: 400",
- "*helpShell*topicList.font: -*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*",
- "*helpShell*text*font: 7x13",
-
- "*PrintSetup*Dialog*value: 0",
- "*PrintSetup*Dialog*value.translations: #override \\n <Key>Return: DoDialog()",
- "*PrintSetup*help.Label: \\ help ",
- "*PrintSetup*print.Label:\\ print ",
- "*PrintSetup*done.Label: \\ done ",
- "*PrintSetup*names.label: interesting names",
- "*PrintSetup*cellSize.label: cell size",
- "*PrintSetup*gridSize.label: grid thick.",
- "*PrintSetup*pageWidth.label: page width",
- "*PrintSetup*pageHeight.label: page height",
- "*PrintSetup*topMargin.label: top margin",
- "*PrintSetup*bottomMargin.label: bottom margin",
- "*PrintSetup*leftMargin.label: left margin",
- "*PrintSetup*rightMargin.label: right margin",
- "*PrintSetup*terrainGray.label: terrain gray",
- "*PrintSetup*enemyGray.label: enemy gray",
- "*PrintSetup*borderWidth.label: border thick.",
- "*PrintSetup*connWidth.label: conn thick.",
- "*PrintSetup*Help.title: *PrintSetup help",
- "*PrintSetup*Help*baseTranslations: #override \\n <Key>Return: DoneHelp() \\n <Key>Escape: DoneHelp() \\n <Btn1Down>: DoneHelp()",
- "*PrintSetup*Help*helpDone.Label: \\ done ",
-
- "*OK.label: OK",
- "*Cancel.label: Cancel",
- NULL
- };
-
- int announced = FALSE;
-
- char *announcemsg = NULL;
-
- int nargs;
- Arg tmpargs[100];
-
- XtAppContext thisapp;
-
- Widget thistoplevel;
-
- Widget choiceshell = NULL;
-
- Widget scenarioshell = NULL;
-
- XtActionsRec quit_actions_table[] = {
- { "wm-quit", quit_program },
- };
-
- static void
- quit_program(wdgt, event, params, num_params)
- Widget wdgt;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- {
- Side *side;
- Map *map;
-
- /* The side with toplevel matching 'wdgt' just quit. */
- if (find_side_and_map_via_a_toplevel(wdgt, &side, &map)) {
- if (side->ui->shell == wdgt) {
- /* Go into the standard quit command. */
- do_quit(side, map);
- } else if (side->ui->help_shell == wdgt) {
- popdown_help(side);
- }
- }
- }
-
- /* The main program. */
-
- int
- main(argc, argv)
- int argc;
- char *argv[];
- {
- init_library_path(NULL);
- printf("\n Welcome to X11 Xconq version %s\n\n",
- version_string());
- printf("%s", license_string());
- print_any_news();
- /* Fiddle with game module structures. */
- clear_game_modules();
- /* Set up empty data structures. */
- init_data_structures();
- /* Do the usual Xt application setup. */
- /* Note that this opens one display by default, which means that
- later code should take note and not try to open this a second time.
- Also, this will absorb all X-related arguments - anything remaining
- is either a generic Xconq option or a mistake. */
- xoptions_count = XtNumber(xoptions);
- thistoplevel =
- XtAppInitialize(&thisapp, PROGRAMCLASSNAME,
- xoptions, XtNumber(xoptions), &argc, argv,
- fallback_resources, (ArgList) NULL, 0);
-
- parse_command_line(argc, argv, general_options);
-
- if (popup_dialog) {
- collect_possible_games();
- popup_game_dialog();
- }
-
- if (popup_dialog) {
- check_player_displays();
- } else {
- load_all_modules();
- check_game_validity();
- parse_command_line(argc, argv, variant_options);
- set_variants_from_options();
- parse_command_line(argc, argv, player_options);
- set_players_from_options();
- make_trial_assignments();
- check_player_displays();
- /* Complain about anything that's left. */
- parse_command_line(argc, argv, leftover_options);
- /* (still need to merge some databases derived from display) */
- }
-
- /* And, perform some once per application context initialization... */
- XtAppAddActions(thisapp, quit_actions_table, XtNumber(quit_actions_table));
- add_map_actions();
- XtAppAddTimeOut(thisapp, 10, run_game_proc, NULL);
- XtAppAddWorkProc(thisapp, run_game_idle, NULL);
-
- /* Do the time-consuming part of setup calculations. */
- calculate_globals();
- run_synth_methods();
- final_init();
- assign_players_to_sides();
- print_instructions();
- run_game(0);
- /* Get the displays set up, but don't draw anything yet. */
- init_all_displays();
- /* Now bring up the init data on each display. */
- init_redraws();
- /* Set up the signal handlers. */
- init_signal_handlers();
- init_x_signal_handlers();
- notify_instructions();
- /* Go into the main play loop. */
- XtAppMainLoop(thisapp);
- /* Humor the compiler. */
- return 0;
- }
-
- unsigned long EffectiveMpTime = 1000; /* The default - 1 second */
-
- static void
- run_game_proc(client_data, id)
- XtPointer client_data;
- XtIntervalId *id;
- {
- Side *side;
- Map *map;
- Unit *unit;
- unsigned long interval;
- Boolean PlayersStillMoving = beforestart = False;
- static enum { slow, fast } last_message = slow;
-
- /* Run the kernel itself. */
- run_game(1);
- /* See if any human's are still moving... */
- for_all_sides(side) {
- if (active_display(side)) {
- /* Is this player still moving? */
- if (side->ingame &&
- side_has_display(side) &&
- !side->finishedturn &&
- /* !side_has_ai(side) && */
- side_initacp(side) > 0 &&
- side_acp_human(side) > 0) {
- PlayersStillMoving = True;
- }
- }
- }
- /* If any players are still moving, then don't Timeout again until */
- /* the required number of seconds have passed. */
- /* Otherwise, call again quickly. */
- /* interval is in milliseconds. */
- if (PlayersStillMoving) {
- interval = EffectiveMpTime;
- if (last_message != slow) {
- if (DebugG)
- notify_all("Next turn; reverting back to slow machine time mode.");
- last_message = slow;
- }
- } else {
- interval = 1;
- if (last_message != fast) {
- if (DebugG)
- notify_all("All human players are done moving; switching to fast machine player mode.");
- last_message = fast;
- }
- }
-
- /* Call again in a bit... */
- XtAppAddTimeOut(thisapp, interval, run_game_proc, NULL);
- }
-
- static Boolean
- run_game_idle(clientdata)
- XtPointer clientdata;
- {
- Side *side;
- Map *map;
- Unit *unit;
-
- /* See if we should jump to another unit and make it current. */
- for_all_sides(side) {
- if (active_display(side)) {
- for_all_maps(side, map) {
- if (map->curtool == movetool) {
- unit = autonext_unit_inbox(side, map->curunit, map->vp);
- if (unit != NULL)
- set_current_unit(side, map, unit);
- }
- }
- }
- }
- /* Call us again! */
- return False;
- }
-
- void
- notify_instructions()
- {
- Obj *instructions = mainmodule->instructions, *rest;
-
- if (instructions != lispnil) {
- if (stringp(instructions)) {
- notify_all("%s", c_string(instructions));
- } else if (consp(instructions)) {
- for (rest = instructions; rest != lispnil; rest = cdr(rest)) {
- if (stringp(car(rest))) {
- notify_all("%s", c_string(car(rest)));
- } else {
- /* (should probably warn about this case too) */
- }
- }
- } else {
- run_warning("Instructions are of wrong type");
- }
- } else {
- notify_all("(no instructions supplied)");
- }
- }
-
- /* The default (human) player is the current user on the current display. */
-
- Player *
- add_default_player()
- {
- Player *player = add_player();
-
- player->name = getenv("USER");
- player->configname = getenv("XCONQ_CONFIG");
- player->displayname = getenv("DISPLAY");
- return player;
- }
-
- /* An init error needs to have the command re-run. */
-
- void
- low_init_error(str)
- char *str;
- {
- fprintf(stderr, "Error: %s.\n", str);
- fflush(stderr);
- exit(1);
- }
-
- /* A warning just gets displayed, no other action is taken. */
-
- void
- low_init_warning(str)
- char *str;
- {
- fprintf(stderr, "Warning: %s.\n", str);
- fflush(stderr);
- }
-
- void
- low_run_error(str)
- char *str;
- {
- close_displays();
- fprintf(stderr, "Error: %s.\n", str);
- fflush(stderr);
- fprintf(stderr, "Saving the game...");
- write_entire_game_state(saved_game_filename());
- fprintf(stderr, " done.\n");
- exit(1);
- }
-
- /* Runtime warnings are for when it's important to bug the players,
- usually a problem with Xconq or a game design. */
-
- void
- low_run_warning(str)
- char *str;
- {
- notify_all("Warning: %s; continuing...", str);
- }
-
- void
- init_x_signal_handlers()
- {
- if (!Debug) {
- XSetErrorHandler(handle_x_error);
- XSetIOErrorHandler(handle_xio_error);
- XtAppSetErrorHandler(thisapp, handle_xt_error);
- }
- }
-
- /* Handlers for X catastrophes attempt to do a save first. */
-
- static int
- handle_x_error (dpy, evt)
- Display *dpy;
- XErrorEvent *evt;
- {
- static int num_errors = 0;
- char buf[BUFSIZE];
-
- XGetErrorText(dpy, evt->error_code, buf, BUFSIZE);
- fprintf(stderr, "\nX error on display %s: %s\n", DisplayString(dpy), buf);
- if (++num_errors >= 10) {
- printf("\nX error: trying emergency save!\n");
- /* Note that if the save fails too, we're totally hosed. */
- /* (should use configurable name here) */
- write_entire_game_state("ack!.xconq");
- abort();
- }
- return 0;
- }
-
- static int
- handle_xio_error (dpy)
- Display *dpy;
- {
- fprintf(stderr, "\nX IO error on display %s: trying emergency save!\n",
- DisplayString(dpy));
- write_entire_game_state("ack!.xconq");
- abort();
- return 0;
- }
-
- static void
- handle_xt_error(msg)
- String msg;
- {
- fprintf(stderr, "Xt error: %s\n", msg);
- /* Get a core dump to debug with. */
- abort();
- }
-
- /* Reading is usually pretty fast, so don't do anything special here. */
-
- void
- announce_read_progress()
- {
- }
-
- /* Announce the start of a time-consuming computation. */
-
- void
- announce_lengthy_process(msg)
- char *msg;
- {
- n_seconds_elapsed(0);
- announcemsg = copy_string(msg);
- if (announcemsg) {
- printf("%s;", announcemsg);
- announcemsg = NULL;
- fflush(stdout);
- announced = TRUE;
- }
- }
-
- /* Announce the making of progress on the computation. */
-
- void
- announce_progress(percentdone)
- int percentdone;
- {
- if (n_seconds_elapsed(2)) {
- printf(" %d%%,", percentdone);
- fflush(stdout);
- announced = TRUE;
- }
- }
-
- /* Announce the end of the time-consuming computation. */
-
- void
- finish_lengthy_process()
- {
- if (announced) {
- printf(" done.\n");
- announced = FALSE;
- }
- }
-
- /* All update_xxx_display callbacks are here. */
-
- /* Draw an individual detailed hex, as a row of one, on all maps. */
-
- void
- update_cell_display(side, x, y, rightnow)
- Side *side;
- int x, y, rightnow;
- {
- Map *map;
-
- if (active_display(side)) {
- for_all_maps(side, map) {
- draw_row(side, map, x, y, 1, TRUE);
- if (map->curunit && map->curunit->x == x && map->curunit->y == y) {
- draw_current(side, map);
- }
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- /* The kernel calls this to update info about the given side. */
-
- void
- update_side_display(side, side2, rightnow)
- Side *side, *side2;
- int rightnow;
- {
- Map *map;
-
- if (active_display(side)) {
- for_all_maps(side, map) {
- draw_side_info(side, map, side2);
- if (endofgame) {
- side->ui->mayseeall = TRUE;
- update_controls(side, map);
- }
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- /* The kernel calls this to update info about the given unit. */
-
- void
- update_unit_display(side, unit, rightnow)
- Side *side;
- Unit *unit;
- int rightnow;
- {
- Map *map;
-
- if (active_display(side) && unit != NULL) {
- if (inside_area(unit->x, unit->y)) {
- update_cell_display(side, unit->x, unit->y, rightnow);
- }
- /* Redraw any/all info about unit and its side. */
- for_all_maps(side, map) {
- draw_map_info(side, map);
- draw_side_info(side, map, unit->side);
- update_unit_type_list(side, map, unit->type);
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_unit_acp_display(side, unit, rightnow)
- Side *side;
- Unit *unit;
- int rightnow;
- {
- if (active_display(side)) {
- }
- }
-
- void
- update_action_result_display(side, unit, rslt, rightnow)
- Side *side;
- Unit *unit;
- int rslt, rightnow;
- {
- Action *action;
- Unit *unit2;
- char *unit2handle = NULL;
-
- if (active_display(side)) {
- action = &(unit->act->nextaction);
- switch (rslt) {
- case A_ANY_DONE:
- /* (anything worthwhile to show?) */
- break;
- case A_FIRE_AT_TOO_FAR:
- unit2 = find_unit(action->args[0]);
- if (unit2) {
- unit2handle = unit_handle(side, unit2);
- if (unit2handle)
- unit2handle = strdup(unit2handle);
- notify(side, "Distance to %s (%d) is out of range (%d) of %s.",
- unit2handle ? unit2handle : "target",
- distance(unit->x, unit->y, unit2->x, unit2->y),
- u_range(unit->type),
- unit_handle(side, unit));
- if (unit2handle)
- free(unit2handle);
- } else {
- notify(side, "That is out of range of your %s.",
- unit_handle(side, unit));
- }
- break;
- default:
- break;
- }
- if (Debug) {
- notify(side, "%s %s %s!", unit_desig(unit),
- action_desig(action), hevtdefns[rslt].name);
- }
- }
- }
-
- /* The kernel calls this to update the global game state. */
-
- void
- update_turn_display(side, rightnow)
- Side *side;
- int rightnow;
- {
- int u;
- Map *map;
-
- if (active_display(side)) {
- for_all_maps(side, map) {
- draw_game_state(side, map);
- /* update view in panner */
- draw_view_in_panner(side, map);
- for_all_unit_types(u) {
- update_unit_type_list(side, map, u);
- }
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_action_display(side, rightnow)
- Side *side;
- int rightnow;
- {
- Map *map;
-
- if (active_display(side)) {
- /* show state of actions */
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_event_display(side, hevt, rightnow)
- Side *side;
- HistEvent *hevt;
- int rightnow;
- {
- int mayseeall, u, uid;
- Unit *unit;
- Side *side2;
- Map *map;
-
- if (active_display(side)) {
- switch (hevt->type) {
- case H_SIDE_LOST:
- if (hevt->data[0] == side_number(side)) {
- notify(side, "You lost!");
- } else {
- notify(side, "%s lost!", side_desig(side_n(hevt->data[0])));
- }
- break;
- case H_SIDE_WON:
- if (hevt->data[0] == side_number(side)) {
- notify(side, "You won!");
- } else {
- notify(side, "%s won!", side_desig(side_n(hevt->data[0])));
- }
- break;
- case H_GAME_ENDED:
- notify(side, "The game is over!");
- /* Enable us to see everything on the map accurately. */
- side->ui->mayseeall = TRUE;
- for_all_maps(side, map) {
- update_controls(side, map);
- }
- break;
- case H_UNIT_COMPLETED:
- side2 = side_n(hevt->data[0]);
- unit = find_unit(hevt->data[1]);
- if (unit != NULL) {
- if (side2 == side) {
- notify(side, "You completed %s.",
- unit_handle(side, unit));
- } else {
- notify(side, "%s completed %s.",
- side_desig(side2), unit_handle(side2, unit));
- }
- }
- break;
- case H_UNIT_CREATED:
- side2 = side_n(hevt->data[0]);
- unit = find_unit(hevt->data[1]);
- if (unit != NULL) {
- if (side2 == side) {
- notify(side, "You created %s.",
- unit_handle(side, unit));
- } else {
- notify(side, "%s created %s.",
- side_desig(side2), unit_handle(side2, unit));
- }
- }
- break;
- default:
- /* No special display desired. */
- break;
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_fire_at_display(side, unit, unit2, m, rightnow)
- Side *side;
- Unit *unit, *unit2;
- int m, rightnow;
- {
- int i, sx1, sy1, sw1, sh1, sx2, sy2, sw2, sh2, dx, dy, xx, yy;
- int startticks, innerticks;
- char *xxx, extrabuf[BUFSIZE];
- Map *map;
-
- if (active_display(side)) {
- i = 0;
- for_all_maps(side, map) {
- x_xform_unit(side, map, unit, &sx1, &sy1, &sw1, &sh1);
- x_xform_unit(side, map, unit2, &sx2, &sy2, &sw2, &sh2);
- /* Offset to draw lines from the middle of the units' images. */
- sx1 += sw1 / 2; sy1 += sh1 / 2;
- sx2 += sw2 / 2; sy2 += sh2 / 2;
- /* Draw one segment of a line between the units. */
- dx = (sx2 - sx1) / 4; dy = (sy2 - sy1) / 4;
- xx = sx1 + ((i / 2) % 4) * dx; yy = sy1 + ((i / 2) % 4) * dy;
- /* (should actually draw something) */
- ++i;
- }
- xxx = unit_handle(side, unit);
- strcpy(extrabuf, xxx);
- notify(side, "%s fired at %s!",
- extrabuf, unit_handle(side, unit2));
- }
- }
-
- /* This is for animation of fire-into actions. */
-
- void
- update_fire_into_display(side, unit, x, y, z, m, rightnow)
- Side *side;
- Unit *unit;
- int x, y, z, m, rightnow;
- {
- }
-
- /* Updates to clock need to be sure that display changes immediately. */
-
- void
- update_clock_display(side, rightnow)
- Side *side;
- int rightnow;
- {
- Map *map;
-
- if (active_display(side)) {
- for_all_maps(side, map) {
- draw_game_clocks(side, map);
- }
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_message_display(side, sender, str, rightnow)
- Side *side, *sender;
- char *str;
- int rightnow;
- {
- Map *map;
-
- if (active_display(side)) {
- notify(side, "From %s: \"%s\"",
- (sender != NULL ? short_side_title(sender) : "<anon>"), str);
- if (rightnow)
- flush_output(side);
- }
- }
-
- void
- update_all_progress_displays(str, s)
- char *str;
- int s;
- {
- }
-
- void
- flush_display_buffers(side)
- Side *side;
- {
- if (active_display(side)) {
- flush_output(side);
- }
- }
-
- void
- update_everything()
- {
- Side *side;
-
- for_all_sides(side) {
- if (active_display(side)) {
- /* (update all maps?) */
- }
- }
- }
-
- /* Close all displays that are still open. */
-
- void
- close_displays()
- {
- Side *side;
-
- for_all_sides(side) {
- if (active_display(side))
- close_display(side);
- }
- }
-
- /* This routine should be called before any sort of normal exit. */
-
- void
- exit_xconq(side)
- Side *side;
- {
- /* (should this really happen first?) */
- close_displays();
- /* maybe record in scorefile */
- printf("%s\n", exit_commentary(side));
- exit(0);
- }
-
- void
- printlisp(obj)
- Obj *obj;
- {
- fprintlisp(stdout, obj);
- }
-
- int
- #ifdef __STDC__
- schedule_movie(Side *side, enum movie_type movie, ...)
- #else
- schedule_movie(side, movie)
- Side *side;
- enum movie_type movie;
- #endif
- {
- return FALSE;
- }
-
- void
- play_movies(sidemask)
- SideMask sidemask;
- {
- }
-
- /* Get rid of extra input events, generally because the situation has
- changed drastically and they are no longer of interest. This routine
- has relatively few valid uses. */
-
- void
- flush_input(side)
- Side *side;
- {
- DGprintf("doing an input flush\n");
- if (active_display(side)) {
- XSync(side->ui->dpy, TRUE);
- }
- }
-
- /* Build a X-compatible widget name, by replacing non-alphanumerics with
- underscores. */
-
- void
- build_name(name, first, second)
- char *name, *first, *second;
- {
- char *ch;
-
- strcpy(name, first);
- strcat(name, second);
- for (ch = name; *ch != '\0'; ++ch) {
- if (!isalnum(*ch))
- *ch = '_';
- }
- }
-
- #ifdef DEBUGGING
-
- /* Set all the window backgrounds, borders, GCs, etc, usually to reflect
- inversion of foreground and background. */
-
- void
- reset_color_state(side)
- Side *side;
- {
- XGCValues values;
- unsigned int gcmask = GCForeground | GCBackground;
-
- /* Set the GCs. */
- values.foreground = side->ui->fgcolor;
- values.background = side->ui->bgcolor;
- XChangeGC(side->ui->dpy, side->ui->gc, gcmask, &values);
- XChangeGC(side->ui->dpy, side->ui->textgc, gcmask, &values);
- XChangeGC(side->ui->dpy, side->ui->ltextgc, gcmask, &values);
- XChangeGC(side->ui->dpy, side->ui->unitgc, gcmask, &values);
- }
-
- void
- reset_window_colors(side, win)
- Side *side;
- Window win;
- {
- XSetWindowBackground(side->ui->dpy, win, side->ui->bgcolor);
- XSetWindowBorder(side->ui->dpy, win, side->ui->fgcolor);
- }
-
- #endif /* DEBUGGING */
-
- /* Completely redo all windows, making no assumptions about appearance.
- This is a last-gasp measure, most redrawing should be restricted
- to only the directly affected windows. Also this shouldn't be
- done without the user's permission, since it will blow away impending
- input. */
-
- void
- redraw(side)
- Side *side;
- {
- draw_all_maps(side);
- /* (should do popups also?) */
- flush_output(side);
- flush_input(side);
- }
-
- /* Trivial abstraction - sometimes other routines want to ensure all output
- so far is actually on the screen and not being buffered up somewhere. */
-
- void
- flush_output(side)
- Side *side;
- {
- XFlush(side->ui->dpy);
- }
-
- /* Beep the beeper! */
-
- void
- beep(side)
- Side *side;
- {
- XBell(side->ui->dpy, side->ui->screen);
- }
-
- /* Send a message to everybody who's got a screen. */
-
- #ifdef __STDC__
- void
- notify_all(char *fmt, ...)
- #else
- void
- notify_all(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- char *fmt;
- long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- #endif
- {
- char tmpnbuf[BUFSIZE]; /* tmp buf for notices only. */
- Side *side;
-
- for_all_sides(side) {
- if (active_display(side)) {
- #ifdef __STDC__
- {
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(tmpnbuf, fmt, ap);
- va_end(ap);
- }
- #else
- sprintf(tmpnbuf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- #endif
- low_notify(side, tmpnbuf);
- }
- }
- }
-
- #ifdef __STDC__
- void
- notify(Side *side, char *fmt, ...)
- #else
- void
- notify(side, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- Side *side;
- char *fmt;
- long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- #endif
- {
- char tmpnbuf[BUFSIZE];
-
- if (active_display(side)) {
- #ifdef __STDC__
- {
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(tmpnbuf, fmt, ap);
- va_end(ap);
- }
- #else
- sprintf(tmpnbuf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- #endif
- low_notify(side, tmpnbuf);
- }
- }
-
- void
- low_notify(side, str)
- Side *side;
- char *str;
- {
- char tmpnbuf[BUFSIZE];
- Map *map;
-
- if (active_display(side)) {
- strcpy(tmpnbuf, str);
- /* Always capitalize first char of notice. */
- if (islower(tmpnbuf[0]))
- tmpnbuf[0] = toupper(tmpnbuf[0]);
- /* Paste into a subwindow of each map window. */
- for_all_maps(side, map) {
- textw_printf(map->history, "%s\n", tmpnbuf);
- }
- DGprintf("To %s: %s\n", side_desig(side), tmpnbuf);
- }
- }
-
- /* General text drawer. */
-
- void
- draw_text(side, win, x, y, str, color)
- Side *side;
- Window win;
- int x, y, color;
- char *str;
- {
- XFontStruct *font = side->ui->textfont;
- GC gc = side->ui->textgc;
- Display *dpy = side->ui->dpy;
-
- y += font->max_bounds.ascent;
- XSetForeground(dpy, gc, color);
- /* If "color" is bg, assume we want reverse video. */
- XSetBackground(dpy, gc, (color == side->ui->bgcolor ? side->ui->fgcolor : side->ui->bgcolor));
- XDrawImageString(dpy, win, gc, x, y, str, strlen(str));
- #ifdef STUPIDFLUSH
- XFlush(dpy);
- #endif STUPIDFLUSH
- }
-
- /* Frequently-called routine to draw text in the foreground color. */
-
- void
- draw_fg_text(side, win, x, y, str)
- Side *side;
- Window win;
- int x, y;
- char *str;
- {
- draw_text(side, win, x, y, str, side->ui->fgcolor);
- }
-
- XawTextPosition
- widget_text_length(w)
- Widget w;
- {
- return XawTextSourceScan (XawTextGetSource (w),
- (XawTextPosition) 0,
- XawstAll, XawsdRight, 1, TRUE);
- }
-
- #if 0
- void
- move_caret_to_start(w)
- Widget w;
- {
- XawTextSetInsertionPoint(w, (XawTextPosition) 0);
- }
- #endif
-
- void
- move_caret_to_end(w)
- Widget w;
- {
- XawTextPosition pos;
-
- pos = widget_text_length(w);
- XawTextSetInsertionPoint(w, pos);
- }
-
- static int count_lines PROTO ((Widget w));
-
- static int
- count_lines(w)
- Widget w;
- {
- int nlines;
- XawTextPosition pos, len;
-
- len = widget_text_length(w);
-
- nlines = 0;
- pos = 0;
- while ((pos = XawTextSourceScan(XawTextGetSource(w),
- pos, XawstEOL, XawsdRight, 1, TRUE))
- != XawTextSearchError) {
- nlines++;
- if (pos >= len)
- break;
- }
- return nlines;
- }
-
- static void drop_lines_from_top PROTO ((Widget w, int num));
-
- static void
- drop_lines_from_top(w, num)
- Widget w;
- int num;
- {
- int nlines;
- XawTextPosition pos, len;
- XawTextBlock tb;
- XawTextEditType et;
-
- len = widget_text_length(w);
-
- nlines = num;
- pos = 0;
- while (nlines &&
- (pos = XawTextSourceScan(XawTextGetSource(w),
- pos, XawstEOL, XawsdRight, 1, TRUE))
- != XawTextSearchError) {
- nlines--;
- if (pos >= len)
- break;
- }
-
- if (pos == XawTextSearchError)
- return;
-
- tb.firstPos = 0;
- tb.length = 0;
- tb.ptr = NULL;
- tb.format = FMT8BIT;
-
- /* Can we write to it? */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, &et); nargs++;
- XtGetValues(w, tmpargs, nargs);
-
- if (et == XawtextRead) {
- /* Make it writable. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, XawtextEdit); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
-
- XawTextReplace(w, (XawTextPosition) 0, pos, &tb);
-
- if (et == XawtextRead) {
- /* Set it back. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, et); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
-
- move_caret_to_end(w);
- }
-
- void
- #ifdef __STDC__
- textw_printf(const Widget w, const char *fmt, ...)
- #else
- textw_printf(w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- Widget w;
- char *fmt;
- long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- #endif
- {
- XawTextBlock tb;
- XawTextPosition ins_point;
- XawTextEditType et;
- int nlines;
- char buf[BUFSIZ];
-
- #ifdef __STDC__
- {
- va_list vl;
-
- va_start(vl, fmt);
- (void) vsprintf(buf, fmt, vl);
- va_end(vl);
- }
- #else
- sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- #endif
- if (w == (Widget) NULL) {
- printf("%s", buf);
- return;
- }
-
- tb.ptr = buf;
- tb.length = strlen(buf);
- tb.format = FMT8BIT;
- tb.firstPos = 0;
-
- /* Can we write to it? */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, &et); nargs++;
- XtGetValues(w, tmpargs, nargs);
-
- if (et == XawtextRead) {
- /* Make it writable. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, XawtextEdit); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
- move_caret_to_end(w);
- ins_point = widget_text_length(w);
- XawTextReplace(w, ins_point, ins_point, &tb);
- move_caret_to_end(w);
- if (et == XawtextRead) {
- /* Set it back. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, et); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
- nlines = count_lines(w);
- /* Need to make this a resource. */
- #define maxlines 256
- if (nlines > maxlines)
- drop_lines_from_top(w, nlines - maxlines);
- #undef maxlines
- }
-
- #if 0
- void textw_iprintf PROTO ((const Widget w, const char *fmt, ...));
-
- void
- #ifdef __STDC__
- textw_iprintf(const Widget w, const char *fmt, ...)
- #else
- textw_iprintf(w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- Widget w;
- char *fmt;
- long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- #endif
- {
- XawTextBlock tb;
- XawTextPosition ins_point;
- XawTextEditType et;
- char buf[BUFSIZ];
-
- #ifdef __STDC__
- {
- va_list vl;
-
- va_start(vl, fmt);
- (void) vsprintf(buf, fmt, vl);
- va_end(vl);
- }
- #else
- sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- #endif
- tb.ptr = buf;
- tb.length = strlen(buf);
- tb.format = FMT8BIT;
- tb.firstPos = 0;
-
- /* Can we write to it? */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, &et); nargs++;
- XtGetValues(w, tmpargs, nargs);
-
- if (et == XawtextRead) {
- /* Make it writable. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, XawtextEdit); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
- ins_point = XawTextGetInsertionPoint(w);
- XawTextReplace(w, ins_point, ins_point, &tb);
- if (et == XawtextRead) {
- /* Set it back. */
- nargs = 0;
- XtSetArg(tmpargs[nargs], XtNeditType, et); nargs++;
- XtSetValues(w, tmpargs, nargs);
- }
- }
- #endif
-
- #if 0
- void
- EraseTextWidget(w)
- Widget w;
- {
- XawTextBlock block;
-
- block.ptr = "";
- block.length = 0;
- block.firstPos = 0;
- block.format = FMT8BIT;
-
- XawTextReplace(w, 0, widget_text_length(w), &block);
- /* If this fails, too bad. */
- move_caret_to_end(w);
- }
- #endif
-
- int
- find_side_via_widget(w, sidep)
- Widget w;
- Side **sidep;
- {
- Side *side;
-
- for_all_sides(side) {
- if (active_display(side)) {
- if (XtDisplay(w) == side->ui->dpy) {
- *sidep = side;
- return TRUE;
- }
- }
- }
- return FALSE;
- }
-